package com.matrix.order.converter;

import com.matrix.api.order.vo.OrderBriefVO;
import com.matrix.api.order.vo.OrderDetailVO;
import com.matrix.api.order.vo.OrderItemVO;
import com.matrix.order.domain.model.Order;
import com.matrix.order.domain.model.OrderItem;
import com.matrix.order.domain.model.OrderPayment;
import com.matrix.order.infrastructure.persistence.po.OrderItemPO;
import com.matrix.order.infrastructure.persistence.po.OrderPO;
import com.matrix.order.infrastructure.persistence.po.OrderPaymentPO;
import org.mapstruct.*;
import org.mapstruct.factory.Mappers;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author 有点甜
 * @since 2025/8/5
 */
@Mapper
public interface OrderConverter {

    OrderConverter INSTANCE = Mappers.getMapper(OrderConverter.class);

    OrderPO toOrderPO(Order order);

    @Mapping(target = "items", ignore = true)
    @Mapping(target = "payments", ignore = true)
    @Mapping(target = "shopOwnerId", ignore = true)
    @Mapping(target = "userCouponId", ignore = true)
    @Mapping(target = "merchantCouponId", ignore = true)
    @Mapping(target = "productApi", ignore = true)
    Order toOrder(OrderPO po);

    OrderItemPO toOrderItemPO(OrderItem item);
    OrderItem toOrderItem(OrderItemPO po);
    OrderPaymentPO toOrderPaymentPO(OrderPayment payment);
    OrderPayment toOrderPayment(OrderPaymentPO po);

    @IterableMapping(qualifiedByName = "toBriefVO")
    List<OrderBriefVO> toOrderBriefVOList(List<Order> orders);

    @Named("toBriefVO")
    @Mapping(source = "id", target = "orderId")
    @Mapping(target = "status", expression = "java(order.getStatus().getCode())")
    OrderBriefVO toOrderBriefVO(Order order);

    @Mapping(source = "id", target = "orderId")
    @Mapping(target = "status", expression = "java(order.getStatus().getCode())")
    @Mapping(target = "initialItems", ignore = true)
    @Mapping(target = "addedItems", ignore = true)
    @Mapping(target = "initialItemsAmount", ignore = true)
    @Mapping(target = "addedItemsAmount", ignore = true)
    @Mapping(target = "shopName", ignore = true)
    @Mapping(target = "shopLogoUrl", ignore = true)
    OrderDetailVO toOrderDetailVO(Order order);

    OrderItemVO toOrderItemVO(OrderItem item);

    @AfterMapping
    default void afterMappingOrderToOrderDetailVO(Order order, @MappingTarget OrderDetailVO vo) {
        if (order.getItems() == null || order.getItems().isEmpty()) {
            vo.setInitialItemsAmount(BigDecimal.ZERO);
            vo.setAddedItemsAmount(BigDecimal.ZERO);
            return;
        }

        Map<Boolean, List<OrderItem>> groupedItems = order.getItems().stream()
                .collect(Collectors.partitioningBy(OrderItem::getAdded));

        List<OrderItem> initialItems = groupedItems.get(false);
        List<OrderItem> addedItems = groupedItems.get(true);

        vo.setInitialItems(initialItems.stream().map(this::toOrderItemVO).collect(Collectors.toList()));
        vo.setAddedItems(addedItems.stream().map(this::toOrderItemVO).collect(Collectors.toList()));

        BigDecimal initialAmount = initialItems.stream()
                .map(item -> item.getPrice().multiply(new BigDecimal(item.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        vo.setInitialItemsAmount(initialAmount);

        BigDecimal addedAmount = addedItems.stream()
                .map(item -> item.getPrice().multiply(new BigDecimal(item.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        vo.setAddedItemsAmount(addedAmount);
    }
}
